#ifndef RTP_HANDLER_H
#define RTP_HANDLER_H

#include <iostream>
#include <cstring>
#include <stdio.h>

#include <unordered_map>

#include "Tools.h"

#define RTSP_INTERLEAVE_LENGTH 4
#define RTP_HEADER_LENGTH 12
#define NALU_HEADER_LENGTH 1
#define START_CODE_LENGTH 4

#define MAX_REC_LENGTH 2000
#define RTP_LOG true

enum RTP_STATUS
{
    RTSP_INTERLEAVE,//解析Rtsp间隔
    RTP_HEADER,//解析rtp头
    NALU_HEADER,//解析nalu头
    NALU_FREG_HEADER,//解析分片nalu头
    NALU_DATA,//解析nalu数据
    RTCP_DATA//rtcp信息
};

struct RTSPInterleave
{
    uint8_t magic;
    uint8_t channel;
    uint16_t length;
};

struct RTPHeader
{
    uint8_t cc:4;       // CSRC计数器
    uint8_t x:1;        // 扩展标志
    uint8_t p:1;        // 填充标志
    uint8_t version:2;  // RTP版本，通常为2
 
    uint8_t pt:7;       // 载荷类型
    uint8_t marker:1;   // 标记位，对于某些协议有特定意义（如H.264 NALU）
 
    uint16_t sequenceNumber; // 序列号
    uint32_t timestamp;      // 时间戳
    uint32_t ssrc;          // 同步源标识符
};

struct NaluHeader
{
    uint8_t type:5;
    uint8_t pre:3;
};

class RtpHandler
{
private:  
    static std::unordered_map<int, std::string> NALU_TYPE;

    //数据包解析变量
    int start;//当前的数据解析起始点
    int status;//当前数据解析状态
    int curSeq;//当前接收数据的SEQ
    int startSeq;//当前视频帧的起始SEQ    
    int curPayloadLength;//当前数据包的载荷长度
    int remainPayloadLength;//当前数据包剩余的为解析载荷长度，最后将剩下nalu载荷长度
   
    //数据包信息
    int curIndex;//当前nalu编号
    int curTimestamp;//当前nalu时间戳
    int curType;//当前nalu类型

    //接收缓冲区越界时，拼接数据使用
    int remainDataLength;
    int needDataLength;
    char remainData[20];

    DataNode* startNode;
    DataNode* endNode;
    int curNaluLength;

public:
    RtpHandler(DataNode* _startNode);
    ~RtpHandler();

    //初始化
    bool Init(int _socketFd, float _frameRate, int _flvClientSocketFd);

    //循环解析RTP数据
    bool RtpParser(char* data, int bytesReceived, int curBufferIndex, bool finishFlag, int& latestIdrIndex);
    
    //检测RTP数据是否拆包
    bool CheckCut(char* data, int pieceLength, int bytesReceived);
    
    //处理RTP拆包
    bool RtpParserRemain(char* data, int bytesReceived, int curBufferIndex, int& latestIdrIndex);
};

#endif